//
//  main.cpp
//  ComponentSystem
//
//  Created by Jeppe Nielsen on 9/24/14.
//  Copyright (c) 2014 Jeppe Nielsen. All rights reserved.
//

#include <iostream>
#include <algorithm>
#include "GameWorld.hpp"
#include "Property.hpp"
#include "Tests.hpp"

using namespace Nano;

class Transform : public GameComponent<Transform> {
public:
    float Position;
    void Reset() {
        Position = 0;
    }
};

class Velocity : public GameComponent<Velocity> {
public:
    float Velocity = 0;
};

class Renderable : public GameComponent<Renderable> {
public:
    std::string model;
};

class Mesh : public GameComponent<Mesh> {
public:
    int verts;
};

SYSTEM(VelocitySystem, Transform, Velocity, Renderable)
    
    void ObjectAdded(GameObject* object) {
        Transform* t = object->GetComponent<Transform>();
        std::cout<<"Added "<< t->Position<<" model : "<<object->GetComponent<Renderable>()->model <<std::endl;
    }
    
    void ObjectRemoved(GameObject* object) {
        Transform* t = object->GetComponent<Transform>();
        std::cout<<"Removed "<< t->Position<<" model : "<<object->GetComponent<Renderable>()->model <<std::endl;
    }

    void Update(float dt) {
        std::for_each(std::begin(Objects()), std::end(Objects()), [](GameObject* object){
            object->GetComponent<Transform>()->Position += object->GetComponent<Velocity>()->Velocity;
            std::cout<<"Position = " << object->GetComponent<Transform>()->Position << std::endl;
        });
    }
};

SYSTEM(MeshSystem, Transform, Mesh)

    void ObjectAdded(GameObject* object) {
        std::cout<<"Mesh added " << object->GetComponent<Mesh>()->verts << std::endl;
    }

    void ObjectRemoved(GameObject* object) {
        std::cout<<"Mesh Removed " << object->GetComponent<Mesh>()->verts << std::endl;
    }
};

struct Person {
    int age;
    int height;
};

struct Simple {
    Simple() : Current(this) {}
    int x;
    std::string name;
    Person person;
    
    Property<Simple*, std::string> Current;
};

struct Reciever {
    void Method(Property<Simple*, std::string>::EventData d) {
        std::cout<<"Simple.Current changed " << d.owner->Current << std::endl;
    }
};

int main(int argc, const char * argv[])
{
/*
    Reciever receiver;

    Simple* a = new Simple();
    a->person.age = 32;
    a->person.height = 176;
    a->name = "Jeppe";
    a->Current.Changed += event_handler(&receiver, &Reciever::Method);
    
    Simple* b = new Simple();
    b->operator=(*a);
    
    b->Current = "Hej";
    

    std::cout<<a->name<<std::endl;
    std::cout<<b->person.age<<std::endl;
    std::cout<<b->person.height<<std::endl;
    
    
  */
    
    Tests tests;
    tests.Run();
    
/*
    GameWorld world;
    
    for (int i=0; i<1000000; i++) {
        
        GameObject* object = world.CreateObject();
        object->Remove();
        
    }
    world.Update(0);
  */
    
    
    
    /*
    
    GameWorld graphics;
    GameObject* model = graphics.CreateObject();
    model->AddComponent<Renderable>()->model = "Citroen";
    
    GameWorld world;
    world.AddSystem<VelocitySystem>();
    world.AddSystem<MeshSystem>();
    
    GameObject* car1 = world.CreateObject();
    car1->AddComponent<Velocity>()->Velocity = 0;
    car1->AddComponent<Transform>()->Position = 128;
    car1->AddComponent<Renderable>(model);

    GameObject* car2 = world.CreateObject();
    car2->AddComponent<Transform>()->Position = 1024;
    car2->AddComponent<Velocity>()->Velocity = 0;
    car2->AddComponent<Renderable>(model);
    
    car1->AddComponent<Mesh>()->verts = 500;
    
    world.Update(0);
    //car1->RemoveComponent<Velocity>();
    
    
    for (int i=0; i<10; i++) {
        if (i==5) {
            car2->Remove();
        } else if (i==6) {
            car2 = world.CreateObject();
            car2->AddComponent<Transform>();
            car2->AddComponent<Velocity>()->Velocity = 100;
            car2->AddComponent<Renderable>()->model = "Jeppe";
        }
        world.Update(0);
    }
    */
    return 0;
}

